/**
 * @class OpenLayers.NGMarker
 * @extends OpenLayers.Marker
 */
OpenLayers.NGMarker = OpenLayers.Class(OpenLayers.Marker, {
	
	overlay: null,
	type: '',
	
	/**
	 * 
	 * @return {NG.util.Overlay} overlay
	 */
	getOverlay: function (){
		return this.overlay;
	},
	
	/**
	 * Sets overlay property
	 * @param {NG.util.Overlay} overlay
	 */
	setOverlay: function (overlay) {
		this.overlay = overlay;
	},
	
	/**
	 * This may be used for clearing markers
	 * @return {String} type
	 */
	getType: function (){
		return this.type;
	},
	
	/**
	 * 
	 * @param {String} type
	 */
	setType: function (type){
		this.type = type;
	}
	
});

/**
 * @class OpenLayers.NGMap
 * @extends OpenLayers.Map
 */
OpenLayers.NGMap = OpenLayers.Class(OpenLayers.Map, {
	mapView:null,

	pan: function(dx, dy, options) {
		if (this.mapView.getMode() == MAP_MODE_INFO_POINT || this.mapView.getMode() == MAP_MODE_INFO_POLYGON || this.mapView.getMode() == MAP_MODE_INFO_PATH) {
			return;
		}
        OpenLayers.Map.prototype.pan.apply(this, arguments);
	},
	
    setCenter: function(lonlat, zoom, dragging, forceZoomChange) {
		if (this.mapView.getMode() == MAP_MODE_INFO_POINT || this.mapView.getMode() == MAP_MODE_INFO_POLYGON || this.mapView.getMode() == MAP_MODE_INFO_PATH) {
			return;
		}
        OpenLayers.Map.prototype.setCenter.apply(this, arguments);
    },
    eventListeners: {
    	zoomend: function(e){
    		var map = e.object;
    		NGLogger.info(e.type + ", zoom:" + map.getZoom() + ", resolution: " + map.getResolutionForZoom(map.getZoom()));
    		//
    		var markersLayer = map.mapView.markersLayer;
    		if (!Ext.isEmpty(markersLayer)) {
    			for (var i = 0; i<markersLayer.markers.length; i++) {
    				var marker = markersLayer.markers[i];
    				var size = marker.icon.size;
    				NGLogger.info(marker);
    				/* resize markers ??
     				size = new OpenLayers.Size(size.w + 10, size.h + 10);
    	            marker.icon.setSize(size);
    	            */ 

    			}
    		}
    	},
    	moveend: function (e){
    		//NGLogger.info("MOVEEND" + e);
    	}
    }
});

/**
 * @class OpenLayers.Layer.NGMapServer
 * @extends OpenLayers.Layer.Grid
 */
OpenLayers.Layer.NGMapServer = OpenLayers.Class(OpenLayers.Layer.Grid, {
	workspace:null,
	categoryOffFilter: "",
	mapView:null,
    attribution: app.mapLogoHtml(),
    
	isBaseLayer: true,
    layers: null,
    async: false,
    name: "NetGis",
	transitionEffect: 'resize',
	
	/**
	 * To control how many tiles are included outside the visible map area.
	 * @cfg {Number} buffer
	 */
	buffer:2,
	
    initialize: function(name, url, params, options) {
    	params.ENABLELOCALCACHE = true;
    	OpenLayers.Layer.Grid.prototype.initialize.apply(this, arguments);
    	this.mapView = params.mapView;
    	this.workspace = params.mapView.workspace;
    	this.categoryOffFilter = params.mapView.categoryOffFilter;
        this.tileSize = app.getSettings().createOpenLayersTileSize();
    },
    
    /**
     * 
     * Create a clone of this layer
     * @return {OpenLayers.Layer.MapServer} An exact clone of this layer 
     */
    clone: function (obj) {
        if (obj == null) {
            obj = new OpenLayers.Layer.NGMapServer(this.name,
                                           this.url,
                                           this.params,
                                           this.getOptions());
        }
        obj = OpenLayers.Layer.Grid.prototype.clone.apply(this, [obj]);

        // copy/set any non-init, non-simple values here
        /*
    	workspace:null,
    	categoryOffFilter: "",
    	mapView:null,
    	*/
        return obj;
    },

    /**
     * 
     * @param bounds
     * @param imgDiv
     * @return {String} url
     */
    getURL: function (bounds, imgDiv) {
		var useCache = app.getSettings().useCache();
		var ws = this.workspace;
		var tileSize = app.getSettings().getTileSize();
		var BBOX = bounds.bottom + "," + bounds.left + "," + bounds.top + "," + bounds.right;
    	var cacheKey = this.workspace.getGetMapProxyUrl() + "?.Type=WebgisMapProvider" +
    		"&Mode=GetMap&NCA=_I:" + IMAGEFORMAT_PNG +
    		";_SRID:" + this.workspace.getSRID() +
    		"#SI#" + 
    		";_WS:" + this.workspace.getName() + 
    		";_Url:" + this.workspace.getHost() + "/" + _NG_SRV_EXT +
    		//";COF:3561683690;&BBOX=" + BBOX + "&Width=256&Height=256";
    		";COF:" + this.categoryOffFilter +
    		";&BBOX=" + BBOX + "&Width=" + tileSize + "&Height=" + tileSize;
    	//cacheKey += "&Transparent=True"; //image format must be png for transparency
    	var url = cacheKey.replace('#SI#', ";_S:" + this.mapView.getSessionID());
    	app.views.mapView.mapServer.store.get(cacheKey, imgDiv);
    	//console.log(this.workspace.getName() + " - " + this.mapView.getSessionID());
    	return OpenLayers.Layer.Grid.prototype.getCacheURL.apply(this, [url, imgDiv, cacheKey]);

    },
    
    /**
     * This method uses POST
     * It is not used becaouse response is so slow
     * 
     * @param bounds
     * @param _image
     * @param _url
     * @param positionImage
     */
	getURLasyncDeprecated: function (bounds, _image, _url, positionImage) {
		var useCache = app.getSettings().useCache();
		var ws = this.workspace;
		var cof = this.categoryOffFilter;
		var mw = this.mapView;			
		
		function getMap(getMapCommand, sessionID, mapServer){
			var url = "";
			var req;
			var key = ws.getName() + cof + bounds + (mw.map.getZoom()+"");
			
			function mapOperation(URL) {
        		_image["url"] = URL; 
	    		_image.url = URL;
	    		positionImage.apply(_image);					
			}
			
			if (useCache && NGTileCache.containsKey(key)) {
				var url = NGTileCache.get(key);
				mapOperation(url);
	    		return;
			}
			
			req = NGServiceRequester.executeCommand(getMapCommand, sessionID, {
            	requestFinished: function (response) {
	        		var getMapResponse = new NG.response.GetMap({
	        			xmlData: response
	        		});
	        		url = getMapResponse.getMapUrl();
	        		url = url.replace("localhost", "ss-netgis.dyndns-ip.com");
	        		mapOperation(url);
	        		if (useCache && !NGTileCache.containsKey(key))
	        			NGTileCache.add(key, url);
	        		NGLogger.info("URL:" + url);
            	}
            });
		}
		
		var getMapCommand = new NG.command.GetMap({
        	workspaceName: ws.getName()
        	,runXmlUrl: ws.getRunXmlUrl()
        	,categoryOffFilter: cof
        	,bbox: bounds
        });					
		
		var session = NGServiceRequester.isAlreadyLoggedIn(ws.getUsername(), ws.getLoginUrl());
		if (session) {
			getMap(getMapCommand, session.sessionID, this);
		} else {
			NGServiceRequester.login(ws.getUsername(), ws.getPassword(), ws.getLoginUrl(), {
				loginSuccess: function(sessionID) {
					getMap(getMapCommand, sessionID, this);							
				}
			});
		}
	},
	enableLocalCache:true,
	getGetMapProxyUrl_: function () {
		return "";
	},
	
	CLASS_NAME: "OpenLayers.Layer.NGMapServer"
});

/**
 * @class OpenLayers.Handler.NGPolygon
 * @extends OpenLayers.Handler.Polygon
 * 
 * OpenLayers Draw Controller<br>
 * You have to sent delegator to control as parameter.
 * delegator must have polygonDone function in order to process polygon bounds.
 * otherwise no action will be performed
 */
OpenLayers.Handler.NGPolygon = OpenLayers.Class(OpenLayers.Handler.Polygon, {
	mapView: null,
    initialize: function(control, callbacks, options) {
        OpenLayers.Handler.Polygon.prototype.initialize.apply(this, arguments);
        control.delegator = control.delegator || {}; 
        this.mapView = control.mapView;
        if (!Ext.isFunction(control.delegator.polygonDone)) 
        	control.delegator.polygonDone = Ext.emptyFn;
        Ext.apply(callbacks, {
        	"done": control.delegator.polygonDone
        });
    },
    CLASS_NAME: "OpenLayers.Handler.NGPolygon"
});

/**
 * @class OpenLayers.Handler.NGPoint
 * @extends OpenLayers.Handler.Point
 * 
 * You have to sent delegator to control as parameter.
 * Delegator must have pointDone function in order to process point coordinates
 * otherwise no action will be performed.
 */
OpenLayers.Handler.NGPoint = OpenLayers.Class(OpenLayers.Handler.Point, {
	mapView: null,
    initialize: function(control, callbacks, options) {
        OpenLayers.Handler.Point.prototype.initialize.apply(this, arguments);
        control.delegator = control.delegator || {}; 
        this.mapView = control.mapView;
        if (!Ext.isFunction(control.delegator.pointDone)) 
        	control.delegator.pointDone = Ext.emptyFn;
        Ext.apply(callbacks, {
        	"done": control.delegator.pointDone
        });
    },
    CLASS_NAME: "OpenLayers.Handler.NGPoint"
});

/**
 * @class OpenLayers.Handler.NGPath
 * @extends OpenLayers.Handler.Path
 * 
 * You have to send delegator to control as parameter.
 * Delegator must have pathDone function in order to process point coordinates
 * otherwise no action will be performed.
 * 
 */
OpenLayers.Handler.NGPath = OpenLayers.Class(OpenLayers.Handler.Path, {
	mapView: null,
    initialize: function(control, callbacks, options) {
        OpenLayers.Handler.Point.prototype.initialize.apply(this, arguments);
        control.delegator = control.delegator || {}; 
        this.mapView = control.mapView;
        if (!Ext.isFunction(control.delegator.pathDone)) 
        	control.delegator.pathDone = Ext.emptyFn;
        Ext.apply(callbacks, {
        	"done": control.delegator.pathDone,
        	"point": function (path){
        		Ext.dispatch({
        			controller: app.controllers.mapView,
        			action: 'addMarker',
        			
    				point: new OpenLayers.LonLat(path.x, path.y),
    				imageUrl: NG_SHORTESTPATH_MARKER_IMAGEURL,
    				clickable: false,
    				center: false,
    				type: 'path'
        		});
        	}
        });
    },
    CLASS_NAME: "OpenLayers.Handler.NGPath"
});

OpenLayers.Control.EndDrawing = OpenLayers.Class(OpenLayers.Control, {
	
	X: 4,
	Y: 100,
    buttons: null,
    
    /**
     * view of the map
     */
    mapView: null,

    /** 
     * Property: position
     * {<OpenLayers.Pixel>} 
     */
    position: null,
	
    position: null,

    /**
     * Constructor: OpenLayers.Control.PanZoom
     * 
     * Parameters:
     * options - {Object}
     */
    initialize: function(options) {
        this.position = new OpenLayers.Pixel(this.X, this.Y);
        OpenLayers.Control.prototype.initialize.apply(this, arguments);
        this.mapView = options.mapView;
    },

    /**
     * APIMethod: destroy
     */
    destroy: function() {
        this.removeButtons();
        this.buttons = null;
        this.position = null;
        OpenLayers.Control.prototype.destroy.apply(this, arguments);
    },

    /**
     * Method: removeButtons
     */
    removeButtons: function() {
        for(var i=this.buttons.length-1; i>=0; --i) {
            this._removeButton(this.buttons[i]);
        }
    },

    /**
     * Method: _removeButton
     * 
     * Parameters:
     * btn - {Object}
     */
    _removeButton: function(btn) {
        OpenLayers.Event.stopObservingElement(btn);
        btn.map = null;
        btn.getSlideFactor = null;
        this.div.removeChild(btn);
        OpenLayers.Util.removeItem(this.buttons, btn);
    },
    
    draw: function() {
        OpenLayers.Control.prototype.draw.apply(this, arguments);

        // place the controls
        this.buttons = [];
        px = this.position;

        var sz = new OpenLayers.Size(36, 36);
        var centered = new OpenLayers.Pixel(px.x+sz.w/2 - 5, px.y);

        this._addButton("panup", "ok.png", centered, sz);
        
        return this.div;
    },
    
    /**
     * 
     * @param btn
     */
    _handler: function (evt, btn) {
    	alert("Polygon ve line çiziminde sonlandıracak");
    	if (app.views.mapView.polygonLayerControl.active === true)
    		app.views.mapView.polygonLayerControl.finishSketch();
    	else if (app.views.mapView.pathLayerControl.active === true)
    		app.views.mapView.pathLayerControl.finishSketch();
    },
    
    activate: function () {
        OpenLayers.Control.prototype.activate.apply(this);
        console.log("activated");
        this.buttons[0].style.display = "block";        
    },
    
    deactivate: function () {
        OpenLayers.Control.prototype.deactivate.apply(this);
        console.log("deactivated");
        this.buttons[0].style.display = "none";
    },
    
    _addButton:function(id, img, xy, sz) {
        var imgLocation = OpenLayers.Util.getImagesLocation() + img;
        var btn = OpenLayers.Util.createAlphaImageDiv(
                                    this.id + "_" + id, 
                                    xy, sz, imgLocation, "absolute");
        btn.style.cursor = "pointer";
        //we want to add the outer div
        this.div.appendChild(btn);

        btn.action = id;
        btn.mapView = this.mapView;

        OpenLayers.Event.observe(btn, "dblclick", 
            OpenLayers.Function.bindAsEventListener(this._handler, btn));
        OpenLayers.Event.observe(btn, "click", 
            OpenLayers.Function.bindAsEventListener(this._handler, btn));
        
        //we want to remember/reference the outer div
        this.buttons.push(btn);
        return btn;
    },
    
    updateEndDrawing: function () {
    	
    },
    
    CLASS_NAME: "OpenLayers.Control.EndDrawing"
});
